﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Fraction
{
    public class CFraction
    {
        //Properties of class Fraction
        //Tu so
        private int _numerator;

        public int Numerator
        {
            get { return _numerator; }
            set { _numerator = value; }
        }
        //Mau so
        private int _denominator;

        public int Denominator
        {
            get { return _denominator; }
            set { _denominator = value; }
        }

        #region defaultConstructor
        public CFraction()
        {
            _numerator = 0;
            _denominator = 1;
 
        }
        public CFraction(int numerator, int denominator)
        {
            _numerator = numerator;
            _denominator = denominator;
        }

        public CFraction(int iWholeIntNumber)
        {
           // Console.WriteLine("In Constructor(int)");
            _numerator = iWholeIntNumber;
            _denominator = 1;
        }
        #endregion
        #region Convertion
        public static implicit operator CFraction(int theInt)
        {
            return new CFraction(theInt);
        }

        public static implicit operator int(CFraction fraction)
        {
            return (int)(fraction._numerator / fraction._denominator);
        }

        public static implicit operator double(CFraction obj)
        {
            return (double)obj._numerator / obj._denominator;
        }

        public static implicit operator float(CFraction obj)
        {
            return (float)obj._numerator / obj._denominator;
        }
        #endregion
        #region Compare methods
        public static bool operator ==(CFraction lhs, CFraction rhs)
        {
            return (lhs._numerator * rhs._denominator == rhs._numerator * lhs._denominator);
        }

        public static bool operator !=(CFraction lhs, CFraction rhs)
        {
            return (lhs._numerator * rhs._denominator != rhs._numerator * lhs._denominator);
        }

        public static bool operator >(CFraction lhs, CFraction rhs)
        {
            if (lhs._denominator * rhs._denominator > 0)
            {
                return (lhs._numerator * rhs._denominator > rhs._numerator * lhs._denominator);
            }

            return (lhs._numerator * rhs._denominator < rhs._numerator * lhs._denominator);
        }

        public static bool operator <(CFraction lhs, CFraction rhs)
        {
            if (lhs._denominator * rhs._denominator > 0)
            {
                return (lhs._numerator * rhs._denominator < rhs._numerator * lhs._denominator);
            }

            return (lhs._numerator * rhs._denominator > rhs._numerator * lhs._denominator);
        }

        public static bool operator >=(CFraction lhs, CFraction rhs)
        {
            return ((lhs > rhs) || (lhs == rhs));
        }

        public static bool operator <=(CFraction lhs, CFraction rhs)
        {
            return ((lhs < rhs) || (lhs == rhs));
        }
        #endregion
        #region Override Methods
        public override bool Equals(object obj)
        {
            if (!(obj is CFraction))
                return false;

            return this == (CFraction)obj;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override string ToString()
        {
            string s;

            s = this._numerator.ToString() + "/" + this._denominator.ToString();

            return s;
        }
        #endregion
        #region Operator
        public static CFraction operator +(CFraction lhs, CFraction rhs)
        {
            if (lhs == rhs)
            {
                return new CFraction(lhs._numerator + rhs._numerator, lhs._denominator);
            }

            int firstResult = lhs._numerator * rhs._denominator + rhs._numerator * lhs._denominator;
            int secondResult = lhs._denominator * rhs._denominator;

            return (new CFraction(firstResult, secondResult)).Shrink();
        }

        public static CFraction operator -(CFraction lhs, CFraction rhs)
        {
            if (lhs == rhs)
            {
                return new CFraction((lhs._numerator - rhs._numerator), lhs._denominator);
            }

            int firstResult = (lhs._numerator * rhs._denominator) - (rhs._numerator * lhs._denominator);
            int secondResult = lhs._denominator * rhs._denominator;

            return (new CFraction(firstResult, secondResult)).Shrink();
        }

        public static CFraction operator *(CFraction lhs, CFraction rhs)
        {
            int firstResult = lhs._numerator * rhs._numerator;
            int secondResult = lhs._denominator * rhs._denominator;

            return (new CFraction(firstResult, secondResult)).Shrink();
        }

        public static CFraction operator /(CFraction lhs, CFraction rhs)
        {
            int firstResult = lhs._numerator * rhs._denominator;
            int secondResult = lhs._denominator * rhs._numerator;

            return (new CFraction(firstResult, secondResult)).Shrink();
        }
        #endregion
        #region Methods
        bool IsValid()
        {
            return (this._denominator == 0);
        }
        public CFraction Normal()// chuan hoa
        {
            if (this._denominator < 0)
            {
                this._numerator = -this._numerator;
                this._denominator = -this._denominator;
            }
            return this;

        }
        public CFraction Shrink()// ham Shrink sai
        {
            int tempNumerator = Math.Abs(this._numerator);
            int tempDenominator = Math.Abs(this._denominator);

            while (tempNumerator != tempDenominator)
            {
                if (tempNumerator > tempDenominator)
                {
                    tempNumerator -= tempDenominator;
                }
                else if (tempDenominator> tempNumerator)
                {
                    tempDenominator -= tempNumerator;
                }
            }

            this._numerator /= tempNumerator;
            this._denominator /= tempDenominator;

            Normal();

            return this;
        }
        #endregion
     
    }
    
}
